
#include <QSslSocket>
#include <QHttp>
#include <QUrl>
#include <QDomNode>
#include <QMap>
#include <QTemporaryFile>
#include <QImageReader>
#include <QDir>

#include <iostream>
using namespace std;

#include "../header/picasa.h"

Picasa::Picasa()
{
	http = new QHttp;
	
	connect(http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)),
					this, SLOT(readResponseHeader(const QHttpResponseHeader &)));

	connect(http, SIGNAL(requestFinished(int, bool)),
          this, SLOT(slAnyRequestFinished(int, bool)));
  
	connect(http, SIGNAL(requestFinished(int, bool)),
             this, SLOT(slGetExistingAlbums(int, bool)));

	connect(http, SIGNAL(requestFinished(int, bool)),
             this, SLOT(slAuthRequestFinished(int, bool)));

	connect(http, SIGNAL(requestFinished(int, bool)),
             this, SLOT(slPostImage(int, bool)));

	connect(http, SIGNAL(dataSendProgress(int, int)),
             this, SLOT(slSendProgressPostImage(int, int)));

	bufferok = 0;
	PicasaSupportedImageTypes << "bmp" << "gif" << "jpeg" << "png";
}

void Picasa::Auth(const QString& UserName, const QString& Password)
{

	QMap<QString, QString> PostMap;
	PostMap["Email"]   = UserName;
	PostMap["Passwd"]  = Password;
	PostMap["service"] = "lh2";
	PostMap["source"]  = "Piu";

	this->UserName = UserName;
	
	QByteArray myBArray(BuildPostData( PostMap ).toUtf8());
	myBArray.resize(myBArray.size() - 1);
	
	QHttpRequestHeader AuthHeader;
	AuthHeader.setRequest("POST", "/accounts/ClientLogin");
	AuthHeader.setContentType("application/x-www-form-urlencoded");
	
	http->setHost("www.google.com", QHttp::ConnectionModeHttps);

	ResetBuffer(bufferok);
	
	

	httpRequestAuthId = http->request( AuthHeader, myBArray, bufferok);	
}

void Picasa::slAuthRequestFinished(int requestId, bool error)
{
	if( httpRequestAuthId != requestId )
	{
		return;
	}
	
	//disconnect(http, SIGNAL(requestFinished(int, bool)),
  //           this, SLOT(slAuthRequestFinished(int, bool)));

	if(error)
	{
		return;
	}
	
	StringMap ResponseMap;
	ParseAuthResponse( bufferok->data(), ResponseMap );
	
	if( ResponseMap.contains("Error") )
	{
		ThrowError( -1, ResponseMap["Error"] );
		return;
	}
	if( ResponseMap.contains("Auth") )
	{
		GoogleAuthValue = ResponseMap.value("Auth");
		//tut eshio budet pro error =)
	}
	
	emit siAuth( ResponseMap );
	//Director( "/tmp/gr", "Test1" );
	//qDebug() << ResponseMap;
	return;
}

void Picasa::GetExistingAlbums()
{
	if( !GoogleAuthValue.length() )
	{
		ThrowError(-1, "AuthNeeded");
		return;
	}
	
	QHttpRequestHeader Header;
	Header.setRequest("GET", "/data/feed/api/user/" + UserName + "?kind=album");
	Header.setValue("Host", "picasaweb.google.com");
	Header.setValue("Connection","Keep-Alive");
	
	Header.setValue("Authorization", "GoogleLogin auth=" + GoogleAuthValue);

	ResetBuffer(bufferok);
	
	http->setHost("picasaweb.google.com");

	
	httpGetAlbumsId = http->request( Header, "", bufferok);	
	//qDebug() << "Getting albums...";
	return;
}

void Picasa::slGetExistingAlbums(int requestId, bool error)
{
	if( httpGetAlbumsId != requestId)
		return;

	//disconnect( http, SIGNAL(requestFinished(int, bool)), this, SLOT(slGetExistingAlbums(int, bool)));
	
	if(error)
	{
		return;
	}
	
	bufferok->seek(0);
	
	QString ErrorString;
	StringVector Titles; 
	if( !GetAlbumsNames( *bufferok, Titles, ErrorString ) )
	{
		ThrowError( -1, ErrorString );
		return;
	}
	//cout << "Picasa->slGetExAlbums" << endl;
	emit siGetExistingAlbums( Titles );
	//qDebug() << Titles;
}

void Picasa::readResponseHeader(const QHttpResponseHeader &responseHeader)
{
	CurrentResponseHeader = responseHeader;
	//qDebug() << "Header received: " << CurrentResponseHeader.toString();
}

/*
void Picasa::GetCaptchaImage(const QString& CaptchaString)
{
	connect(http, SIGNAL(requestFinished(int, bool)),
             this, SLOT(slGotCaptchaImage(int, bool)));

	TmpFile.remove();
	if(!TmpFile.open())
	{
		qDebug() << "Can't create tmp file for captcha";
		return;
	}
	
	http->setHost("www.google.com", QHttp::ConnectionModeHttps);
	//httpGetAlbumsId = http->request( Header, "", &AlbumsXml);
	httpGetCaptchaId = http->get("/accounts/" + CaptchaString, &TmpFile);
	
	qDebug() << "Getting captcha...";
}

void Picasa::slGotCaptchaImage(int requestId, bool error)
{
	if( httpGetCaptchaId != requestId)
		return;

	if(error)
	{
		return;
	}
	//
	qDebug() << "Here need captcha!, file: " + TmpFile.fileName();
	TmpFile.close();
}
*/
void Picasa::PostImageRequest( const QString& AlbumTitle, const QString& FilePath )
{
	if( !GoogleAuthValue.length() )
	{
		ThrowError(-1, "AuthNeeded");
		return;
	}
	
	QString ImageType( QImageReader::imageFormat( FilePath ) );
	if( !PicasaSupportedImageTypes.contains( ImageType ) )
	{
		ThrowError(-1, "UnsuportedImageType");
		return;
	}
	
	QFile Image( FilePath );
	if( !Image.open(QIODevice::ReadOnly) )
	{
		ThrowError(-1, "CannotOpenReadOnlyImage");
		return;
	}	
	
	QHttpRequestHeader Header;
	Header.setRequest("POST", "/data/feed/api/user/" + UserName + "/album/" + AlbumTitle);
	Header.setValue("Host", "picasaweb.google.com");
	Header.setValue("Connection","Keep-Alive");
	Header.setValue("Authorization", "GoogleLogin auth=" + GoogleAuthValue);
	Header.setValue("Content-Type", "image/" + ImageType);
	
	http->setHost("picasaweb.google.com");
	
	//int LastIndex = postimages.Add( 0 );
	//postimages.ids[LastIndex] = http->request( Header, ImageFile.readAll(), postimages.buffers.at(LastIndex) );
	ResetBuffer(bufferok);
	
	httpPostImageId = http->request( Header, Image.readAll(), bufferok );
}

void Picasa::slPostImage(int requestId, bool error)
{
	if( requestId != httpPostImageId )
		return;

	//disconnect(http, SIGNAL(requestFinished(int, bool)), 0, 0);
	if(error)
	{
		return;
	}
	emit siPostImage();
	//qDebug() << "Image Return: " << bufferok->data();
}

void Picasa::slSendProgressPostImage(int done, int total)
{
	//qDebug() << QObject::tr("Uploaded: %1, of total: %2").arg(done).arg(total);
}

void Picasa::Director( const QString& Directory, const QString& AlbumTitle )
{
/*
	QDir dir( Directory, "", QDir::Name | QDir::IgnoreCase, QDir::Files);
	
	QFileInfoList list = dir.entryInfoList();
	qDebug() << list.size();
	for(int i = 0; i < list.size(); i++)
	{
		QFileInfo fileInfo = list.at(i);
		QString ImageType( QImageReader::imageFormat( fileInfo.filePath() ) );
		if( !PicasaSupportedImageTypes.contains( ImageType ) )
		{
			qDebug() << "File:" << fileInfo.filePath() << "has unsupported type! (" << QImageReader::imageFormat( fileInfo.filePath() ) << ")";
			continue;
		}
		
		QFile Image( fileInfo.filePath() );
		if( !Image.open(QIODevice::ReadOnly) )
		{
			qDebug() << QObject::tr("Can't open file: %1").arg(fileInfo.filePath());
			continue;
		}
		//qDebug() << "Posting file: " << fileInfo.filePath();
		PostImageRequest( AlbumTitle, Image );
	}
	*/
}

bool Picasa::GetAlbumsNames( QIODevice& AlbumsInXml, StringVector& RetVector, QString& ErrorMessage )
{
	QDomDocument doc;
	QString errorStr;
	int errorLine;
	int errorColumn;
	
	if ( !doc.setContent(&AlbumsInXml, true, &errorStr, &errorLine, &errorColumn) )
	{
		ErrorMessage = QObject::tr("Parse error at line %1, column %2:\n%3").arg(errorLine).arg(errorColumn).arg(errorStr);
		return false;
	}

	QDomElement root = doc.documentElement();
	QDomNode node = root.firstChild();
	while (!node.isNull())
	{
		if (node.toElement().tagName() == "entry")
			parseEntry(node.toElement(), RetVector);
		node = node.nextSibling();
	}	
	return true;
}

void Picasa::slAnyRequestFinished( int requestId, bool error )
{
	if(error)
	{
		ThrowError( http->error(), http->errorString() );
	}
}

void Picasa::ThrowError( int ErrorId, const QString& ErrorString)
{
	emit siThrowError( ErrorId, ErrorString );
}

void Picasa::parseEntry(const QDomElement& element, StringVector& AlbumsTitles)
{
	QDomNode node = element.firstChild();
	while (!node.isNull())
	{
		if (node.toElement().tagName() == "title")
		{
			QDomNode childNode = node.firstChild();
			if (childNode.nodeType() == QDomNode::TextNode)
			{
				QString AlbumTitle = childNode.toText().data();
				AlbumsTitles << AlbumTitle;
			}
		}
		node = node.nextSibling();
	}
}

QString Picasa::BuildPostData(const QMap<QString, QString>& map)
{
	QString strPostData;
	QMap<QString, QString>::const_iterator i = map.constBegin();
	while (i != map.constEnd())
	{
		if( strPostData.length() != 0)
			strPostData += "&";
		strPostData += QUrl::toPercentEncoding(i.key(), "", " ") + "=" + QUrl::toPercentEncoding(i.value(), "", " ");
		++i;
	}
	return strPostData;
}

void Picasa::ParseAuthResponse(const QString& AuthResponse, QMap<QString, QString>& FilledMap)
{
	QRegExp rx("([\\w]+)=([^\\s]+)");
	QStringList list;
	int pos = 0;
	while ( (pos = rx.indexIn(AuthResponse, pos) ) != -1)
	{
		FilledMap[rx.cap(1)] = rx.cap(2);
		pos += rx.matchedLength();
	}
}

void Picasa::ResetBuffer( QBuffer*& buffer )
{
	if( buffer == 0 )
	{
		buffer = new QBuffer();
		buffer->open( QIODevice::ReadWrite );
		return;
	}
	
	delete buffer;
	buffer = new QBuffer();
	buffer->open( QIODevice::ReadWrite );
}


